package com.njtoyo.taxi.admin.service.open.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.payment.cmb.CmbPayClient;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverBanking;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverWithdraw;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverWithdrawHistory;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverWithdrawState;
import com.njtoyo.taxi.admin.mapper.master.mapper.DriverBankingMapper;
import com.njtoyo.taxi.admin.mapper.master.mapper.DriverWithdrawHistoryMapper;
import com.njtoyo.taxi.admin.mapper.secondary.entity.ICBCBill;
import com.njtoyo.taxi.admin.mapper.secondary.entity.RefundWrapper;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.IcbcBillMapper;
import com.njtoyo.taxi.admin.service.business.DriverWithdrawHistoryService;
import com.njtoyo.taxi.admin.service.business.DriverWithdrawService;
import com.njtoyo.taxi.admin.service.open.BankService;
import com.taxi.entity.common.RestResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@DS(Const.SECONDARY_DS)
public class BankServiceImpl implements BankService {
    @Autowired
    private IcbcBillMapper icbcBillMapper;
    @Autowired
    private DriverWithdrawService driverWithdrawService;
    @Autowired
    private DriverWithdrawHistoryService driverWithdrawHistoryService;
    @Autowired
    private DriverBankingMapper driverBankingMapper;

    @Override
    public RestResult saveICBCBill(ICBCBill wrapper) {
        wrapper.setCreateTime(DateUtil.date());
        int result = icbcBillMapper.insert(wrapper);
        if (result > 0) {
            return RestResult.success("保存成功");
        }
        return RestResult.success("保存失败");
    }

    @Override
    public RestResult cmbCallback(Map<String, Object> params) {
        String dateStr = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
        String localPath = "/bank/remit/download/" + dateStr;
        if (!FileUtil.exist(localPath)) {
            FileUtil.mkParentDirs(localPath);
        }
        if ("AP".equals(MapUtil.getStr(params, "fileType"))) {
            String fileUrl = MapUtil.getStr(params, "fileUrl");
            String batchStatus = MapUtil.getStr(params, "batchStatus");//S:处理成功,F:处理失败
            String batchNo = MapUtil.getStr(params, "batchNo");
            if ("F".equals(batchStatus)) {
                log.error("批次{}处理失败", batchNo);
                //批次处理失败,表示整个批次失败
                String failReason = MapUtil.getStr(params, "failReason");
                driverWithdrawService.update(Wrappers.<DriverWithdraw>lambdaUpdate().set(DriverWithdraw::getState, DriverWithdrawState.failed).set(DriverWithdraw::getMsg, failReason).eq(DriverWithdraw::getBatchNo, batchNo));

                driverWithdrawHistoryService.update(Wrappers.<DriverWithdrawHistory>lambdaUpdate()
                        .set(DriverWithdrawHistory::getFailReason, failReason)
                        .set(DriverWithdrawHistory::getWithdrawFlag, "F")
                        .eq(DriverWithdrawHistory::getBatchNo, batchNo));


            } else {
                String fileLocalUrl = localPath + "/" + batchNo + ".zip";
                File file = HttpUtil.downloadFileFromUrl(fileUrl, new File(fileLocalUrl));
                log.info("代发批次{}存储地址：{},下载结果：{}", batchNo, file.getPath(), file.exists());
                if (file.exists()) {
                    List<DriverWithdraw> driverWithdraws = driverWithdrawService.list(Wrappers.<DriverWithdraw>lambdaQuery().eq(DriverWithdraw::getBatchNo, batchNo));
                    Map<String, DriverWithdraw> driverWithdrawMap = driverWithdraws.stream().collect(Collectors.toMap(DriverWithdraw::getSerialNo, Function.identity()));
                    File unzipFile = ZipUtil.unzip(fileLocalUrl);
                    File targetFile = null;
                    if (unzipFile.isDirectory()) {
                        final File[] files = unzipFile.listFiles();
                        if (files != null) {
                            targetFile = files[0];
                        }
                    }
                    List<CsvRow> rows = CsvUtil.getReader().read(new File(targetFile.getPath())).getRows();
                    for (CsvRow row : rows) {
                        if (row.getOriginalLineNumber() == 1) {
                            continue;
                        }
                        String serialNo = StrUtil.removeAll(row.get(1), "`");
                        DriverWithdraw driverWithdraw = driverWithdrawMap.get(serialNo);
                        if (ObjectUtil.isNull(driverWithdraw)) {
                            log.info("批次{}csv转账反馈中无流水号{}的结果", batchNo, row.get(1));
                            continue;
                        }
                        String state = StrUtil.removeAll(row.get(5), "`");
                        String bankSerialNo = StrUtil.removeAll(row.get(7), "`");
                        if ("S".equals(state)) {
                            driverWithdraw.setState(DriverWithdrawState.done);
                            String receiptTime = StrUtil.removeAll(row.get(8), "`") + StrUtil.removeAll(row.get(9), "`");
                            driverWithdraw.setReceiptTime(DateUtil.parse(receiptTime, "yyyyMMddHHmmss").toString());
                            driverWithdraw.setBankSerialNo(bankSerialNo);

                            driverWithdrawHistoryService.update(Wrappers.<DriverWithdrawHistory>lambdaUpdate()
                                    .set(DriverWithdrawHistory::getBankSerialNo, bankSerialNo)
                                    .set(DriverWithdrawHistory::getWithdrawFlag, "S")
                                    .eq(DriverWithdrawHistory::getSerialNo, driverWithdraw.getSerialNo()));
                        } else {
                            String failReason = StrUtil.removeAll(row.get(6), "`");
                            driverWithdraw.setState(DriverWithdrawState.failed);
                            driverWithdraw.setMsg(failReason);
                            driverWithdraw.setBankSerialNo(bankSerialNo);

                            driverWithdrawHistoryService.update(Wrappers.<DriverWithdrawHistory>lambdaUpdate()
                                    .set(DriverWithdrawHistory::getBankSerialNo, bankSerialNo)
                                    .set(DriverWithdrawHistory::getWithdrawFlag, "F")
                                    .set(DriverWithdrawHistory::getFailReason, failReason)
                                    .eq(DriverWithdrawHistory::getSerialNo, driverWithdraw.getSerialNo()));
                        }
                        driverWithdrawService.updateById(driverWithdraw);
                    }
                }
            }
        } else if ("AP".equals(MapUtil.getStr(params, "refundType"))) { //发生了退票
            String origRespNo = MapUtil.getStr(params, "origRespNo");
            String refundNote = MapUtil.getStr(params, "refundNote");
            //修改提款记录状态
            driverWithdrawService.update(Wrappers.<DriverWithdraw>lambdaUpdate()
                    .set(DriverWithdraw::getMsg, refundNote)
                    .set(DriverWithdraw::getState, DriverWithdrawState.failed)
                    .eq(DriverWithdraw::getBankSerialNo, origRespNo));

            //更改打款记录状态
            driverWithdrawHistoryService.update(Wrappers.<DriverWithdrawHistory>lambdaUpdate()
                    .set(DriverWithdrawHistory::getWithdrawFlag, "F")
                    .set(DriverWithdrawHistory::getFailReason, refundNote)
                    .eq(DriverWithdrawHistory::getBankSerialNo, origRespNo));
        }
        return RestResult.success();
    }

    @Override
    public RestResult refundOrder(RefundWrapper refundWrapper) {
        if (refundWrapper.getAmount() < refundWrapper.getRefundAmount()) {
            return RestResult.failed("退款金额大于订单金额");
        }
        Map<String, String> resultMap = CmbPayClient.refund(refundWrapper.getRefundNumber(), refundWrapper.getOrderNumber(), refundWrapper.getReason(), refundWrapper.getOrderNumber(), refundWrapper.getRefundNumber(), refundWrapper.getAmount().toString(), refundWrapper.getRefundAmount().toString());
        if ("SUCCESS".equals(resultMap.get("respCode"))) {
            return RestResult.success();
        }
        return RestResult.failed("退款失败");
    }

}
